/*
 * JAutocompleteTextField.java
 *
 * Created on Oct 28, 2007, 11:17:42 PM
 *
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package procrastinator.autocomplete;

import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

/**
 *
 * @author alex
 */
public class JAutocompleteTextField extends JTextField implements FocusListener, DocumentListener {

    private List<String> items;
    private List<ValueChangedListener> listeners;
    private String currentValue = null;
    private boolean ignoreEvents = false;

    public JAutocompleteTextField() {
        super();

        items = new ArrayList<String>();
        listeners = new ArrayList<ValueChangedListener>();

        getDocument().addDocumentListener(this);
        addFocusListener(this);


        // some values
        items.add("Wikipedia");
        items.add("Write paper");
        items.add("foo bar baz");
    }

    public void addValue(String item) {
        items.add(item);
    }

    private String lookup(String prefix) {
        for (String item : items) {
            if (item.toLowerCase().startsWith(prefix.toLowerCase())) {
                return item;
            }
        }

        return null;
    }

    private void setIgnoreEvents(boolean t) {
        ignoreEvents = t;
    }

    public synchronized void insertUpdate(DocumentEvent arg0) {
        //System.err.println("0");
        if (!ignoreEvents) {
            autocomplete();
        }
        //System.err.println("0x");
    }

    public synchronized void removeUpdate(DocumentEvent arg0) {
        //System.err.println("1");
        if (!ignoreEvents) {
           // autocomplete();
        }
        //System.err.println("1x");
    }

    private void autocomplete() {
        final String value = getText();
        final String completed = lookup(value);

        if (completed == null) {
            for (ValueChangedListener listener : listeners) {
                listener.valueChanged(getText());
            }
        } else {
            final JAutocompleteTextField textfield = this;
            currentValue = completed;

            SwingUtilities.invokeLater(new Runnable() {

                public void run() {
                    //System.err.println("a0");
                    synchronized (textfield) {
                      //  System.err.println("a");
                        setIgnoreEvents(true);
                        setText(completed);

                        setCaretPosition(value.length());
                        moveCaretPosition(completed.length());
                        //System.err.println("b");
                        setIgnoreEvents(false);
                        //System.err.println("c");
                    }

                    //System.err.println("c2 " + ignoreEvents);

                    for (ValueChangedListener listener : listeners) {
                        listener.valueChanged(getText());
                    }
                }
            });
        }
    }

    private String updateAutocompletion(String prefix) {
        String completed = lookup(prefix);

        /*
        System.err.println("prefix: " + prefix);
        System.err.println("lookup: " + completed);
         */

        if (completed != null) {
            setText(completed);

            setCaretPosition(prefix.length());
            moveCaretPosition(completed.length());

            return completed;
        } else {
            setText(prefix);
            return prefix;
        }
    }

    public void addValueChangedListener(ValueChangedListener listener) {
        listeners.add(listener);
    }

    public void focusGained(FocusEvent arg0) {
        setBackground(Color.YELLOW);
    }

    public void focusLost(FocusEvent arg0) {
        setBackground(Color.WHITE);
    }

    public void changedUpdate(DocumentEvent arg0) {
    }
}